import threading
from copy import deepcopy

import cv2
import numpy as np
import jy901

head_gyro = jy901.Gyro(0x50)

class Video_task(threading.Thread):
    def __init__(self, camera_id, img_height, img_width):
        super(Video_task, self).__init__()
        self.camera_id = camera_id
        self.img_height = img_height
        self.img_width = img_width
        self.num = 0
        self.open_cam = False
        self.thread_lock = threading.Lock()
        self.thread_exit = False
        
        self.frame = np.zeros((self.img_height, self.img_width, 1), np.uint8) + 200
        cv2.putText(self.frame, 'NO VIDEO', (110, 260), cv2.FONT_HERSHEY_SIMPLEX, 3, 50, 5)
        self.close_jpeg = cv2.imencode('.jpg', self.frame)[1].tobytes()

    def get_frame(self):
        self.thread_lock.acquire()
        frame = deepcopy(self.frame)
        self.thread_lock.release()
        # 因为opencv读取的图片并非jpeg格式，因此要用motion JPEG模式需要先将图片转码成jpg格式图片
        frame = self.rotate_bound(frame,180-head_gyro.get_angle()[1])
        jpeg = cv2.imencode('.jpg', frame)[1]
        return jpeg.tobytes()

    def rotate_bound(self, image, angle):
        # grab the dimensions of the image and then determine the
        # center
        (h, w) = image.shape[:2]
        (cX, cY) = (w // 2, h // 2)
    
        # grab the rotation matrix (applying the negative of the
        # angle to rotate clockwise), then grab the sine and cosine
        # (i.e., the rotation components of the matrix)
        M = cv2.getRotationMatrix2D((cX, cY), -angle, 1.0)
        cos = np.abs(M[0, 0])
        sin = np.abs(M[0, 1])
    
        # compute the new bounding dimensions of the image
        nW = int((h * sin) + (w * cos))
        nH = int((h * cos) + (w * sin))
    
        # adjust the rotation matrix to take into account translation
        M[0, 2] += (nW / 2) - cX
        M[1, 2] += (nH / 2) - cY
    
        # perform the actual rotation and return the image
        return cv2.warpAffine(image, M, (nW, nH))

    def video_feed(self):
        num = self.num
        while num == self.num:
            if self.open_cam == True:
                frame = self.get_frame()
                # 使用generator函数输出视频流， 每次请求输出的content类型是image/jpeg
                yield (b'--frame\r\n'
                       b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n\r\n')
                # 降低帧率，减少cpu占用
                cv2.waitKey(60)
            else:
                # 使用generator函数输出视频流， 每次请求输出的content类型是image/jpeg
                yield (b'--frame\r\n'
                       b'Content-Type: image/jpeg\r\n\r\n' + self.close_jpeg + b'\r\n\r\n')
                # 降低帧率，减少cpu占用
                cv2.waitKey(200)

    def run(self):
        cap = cv2.VideoCapture(self.camera_id)
        while not self.thread_exit:
            if self.open_cam == True:
                ret, frame = cap.read()
                if ret:
                    frame = cv2.resize(frame, (self.img_width, self.img_height))
                    self.thread_lock.acquire()
                    self.frame = frame
                    self.thread_lock.release()
                else:
                    self.thread_exit = True
            else:
                cv2.waitKey(50)
        cap.release()
